package org.bjf.config.ds;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.util.Date;

@Configuration
@MapperScan(basePackages = {"org.bjf.modules.*.mapper",
    "org.bjf.modules.sys.mapper"}, sqlSessionFactoryRef = "userSessionFactory")
public class UserDataSourceConfig {

  static final String PACKAGE = "org.bjf.modules.user.mapper,org.bjf.modules.sys.mapper";
  private static final String MAPPERLOCATIONS = "classpath*:mapper/user/**/*.xml";
  private static final String TYPEALIASESPACKAGE = "org.bjf.modules.user.bean";

  @Bean(name = "userDataSource")
  @ConfigurationProperties(prefix = "custom.datasource.user")
  @Primary
  public DataSource dataSource() {
    return new DruidDataSource();
  }

  @Bean(name = "userTransactionManager")
  @Primary
  public DataSourceTransactionManager transactionManager(
      @Qualifier("userDataSource") DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
  }

  @Bean(name = "userSessionFactory")
  @Primary
  public SqlSessionFactory sessionFactory(
      @Qualifier("userDataSource") DataSource dataSource) throws Exception {

    //===1.mybatis-plus 配置
    DbConfig dbCfg = new DbConfig();
    //主键策略
    dbCfg.setIdType(IdType.AUTO);
    //逻辑删除
    dbCfg.setLogicDeleteValue("1");
    dbCfg.setLogicNotDeleteValue("0");
    GlobalConfig globalConfig = new GlobalConfig();
    globalConfig.setDbConfig(dbCfg);
    globalConfig.setMetaObjectHandler(new TimeMetaObjectHandler());

    // 字段的驼峰下划线转换
    MybatisConfiguration configuration = new MybatisConfiguration();
    configuration.setMapUnderscoreToCamelCase(Boolean.TRUE);
    //枚举支持
    configuration.setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class);

    //===2.构造sessionFactory(mybatis-plus)
    final MybatisSqlSessionFactoryBean sf = new MybatisSqlSessionFactoryBean();
    sf.setDataSource(dataSource);
    sf.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPERLOCATIONS));
    sf.setTypeAliasesPackage(TYPEALIASESPACKAGE);
    sf.setGlobalConfig(globalConfig);
    sf.setConfiguration(configuration);
    // 分页插件
    sf.setPlugins(new Interceptor[]{new PaginationInterceptor()});

    return sf.getObject();
  }


  /**
   * 创建时间和更新时间设置为空，由数据库去维护
   */
  private static class TimeMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
      this.strictInsertFill(metaObject, "ctime", Date.class, null);
      this.strictInsertFill(metaObject, "utime", Date.class, null);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
      this.strictUpdateFill(metaObject, "ctime", Date.class, null);
      this.strictUpdateFill(metaObject, "utime", Date.class, null);
    }
  }
}  